#ifndef _WX_TOKENZRH
#define _WX_TOKENZRH

#include "wx/object.h"
#include "wx/string.h"
#include "wx/arrstr.h"

#define wxDEFAULT_DELIMITERS (wxT(" \t\r\n"))

enum wxStringTokenizerMode {
  wxTOKEN_INVALID = -1,   // set by def ctor until SetString() is called
  wxTOKEN_DEFAULT,        // strtok() for whitespace delims, RET_EMPTY else
  wxTOKEN_RET_EMPTY,      // return empty token in the middle of the string
  wxTOKEN_RET_EMPTY_ALL,  // return trailing empty tokens too
  wxTOKEN_RET_DELIMS,     // return the delim with token (implies RET_EMPTY)
  wxTOKEN_STRTOK          // behave exactly like strtok(3)
};

class wxStringTokenizer : public wxObject {
  public:
    // ctors and initializers
    // default ctor, call SetString() later
    wxStringTokenizer() { m_mode = wxTOKEN_INVALID; }
    // ctor which gives us the string
    wxStringTokenizer( const wxString& str,
                       const wxString& delims = wxDEFAULT_DELIMITERS,
                       wxStringTokenizerMode mode = wxTOKEN_DEFAULT );

    // args are same as for the non default ctor above
    void SetString( const wxString& str,
                    const wxString& delims = wxDEFAULT_DELIMITERS,
                    wxStringTokenizerMode mode = wxTOKEN_DEFAULT );

    // reinitialize the tokenizer with the same delimiters/mode
    void Reinit( const wxString& str );

    // tokens access
    // return the number of remaining tokens
    size_t CountTokens() const;
    // did we reach the end of the string?
    bool HasMoreTokens() const;
    // get the next token, will return empty string if !HasMoreTokens()
    wxString GetNextToken();
    wxChar GetLastDelimiter() const { return m_lastDelim; }
    wxString GetString() const { return m_string.substr( m_pos ); }
    size_t GetPosition() const { return m_pos; }
    wxStringTokenizerMode GetMode() const { return m_mode; }
    // do we return empty tokens?
    bool AllowEmpty() const { return m_mode != wxTOKEN_STRTOK; }
    wxString NextToken() { return GetNextToken(); }

    // compatibility only, don't use
    void SetString( const wxString& to_tokenize, const wxString& delims, bool ( ret_delim ) ) {
      SetString( to_tokenize, delims, wxTOKEN_RET_DELIMS );
    }

    wxStringTokenizer( const wxString& to_tokenize, const wxString& delims, bool ret_delim ) {
      SetString( to_tokenize, delims, ret_delim );
    }

  protected:
    bool IsOk() const { return m_mode != wxTOKEN_INVALID; }
    wxString m_string,              // the string we tokenize
             m_delims;              // all possible delimiters

    size_t   m_pos;                 // the current position in m_string

    wxStringTokenizerMode m_mode;   // see wxTOKEN_XXX values

    wxChar   m_lastDelim;           // delimiter after last token or '\0'
};

wxArrayString wxStringTokenize( const wxString& str, const wxString& delims = wxDEFAULT_DELIMITERS,
                                wxStringTokenizerMode mode = wxTOKEN_DEFAULT );

#endif // _WX_TOKENZRH
